LLM 25일 코스 - Day 3: 토큰화와 임베딩 이해

Day 3: 토큰화와 임베딩 이해

LLM은 텍스트를 직접 이해하지 못합니다. 텍스트를 숫자로 바꾸는 첫 번째 단계가 토큰화(Tokenization) 이고, 그 숫자를 의미 있는 벡터로 바꾸는 것이 임베딩(Embedding) 입니다.

토큰화 알고리즘 비교

알고리즘사용 모델특징
BPE (Byte Pair Encoding)GPT 시리즈가장 빈번한 바이트 쌍을 반복 병합
WordPieceBERTBPE와 유사하나 우도(likelihood) 기반 병합
SentencePieceT5, Llama언어에 독립적, 공백도 토큰으로 처리
UnigrammBART큰 어휘에서 시작해 확률 낮은 토큰 제거

tiktoken으로 토큰화 실습

# pip install tiktoken
import tiktoken

# GPT-4가 사용하는 토크나이저
encoder = tiktoken.encoding_for_model("gpt-4")

text_ko = "대규모 언어모델은 자연어를 이해합니다"
text_en = "Large language models understand natural language"

tokens_ko = encoder.encode(text_ko)
tokens_en = encoder.encode(text_en)

print(f"한국어: {len(tokens_ko)}개 토큰 → {tokens_ko}")
print(f"영어:   {len(tokens_en)}개 토큰 → {tokens_en}")

# 토큰을 다시 텍스트로 복원
for token_id in tokens_ko:
    print(f"  {token_id} → '{encoder.decode([token_id])}'")

한국어는 영어보다 동일한 의미를 표현하는 데 더 많은 토큰이 필요합니다. 이는 비용과 컨텍스트 윈도우 활용에 직접적인 영향을 줍니다.

BPE 알고리즘 직접 구현

def simple_bpe(corpus, num_merges):
    """간소화된 BPE 알고리즘"""
    # 초기: 글자 단위로 분리
    vocab = {}
    for word in corpus:
        chars = list(word) + ["</w>"]
        key = " ".join(chars)
        vocab[key] = vocab.get(key, 0) + 1

    for i in range(num_merges):
        pairs = {}
        for word, freq in vocab.items():
            symbols = word.split()
            for j in range(len(symbols) - 1):
                pair = (symbols[j], symbols[j + 1])
                pairs[pair] = pairs.get(pair, 0) + freq

        if not pairs:
            break
        best_pair = max(pairs, key=pairs.get)
        print(f"병합 {i+1}: '{best_pair[0]}' + '{best_pair[1]}'")

        # 가장 빈번한 쌍을 병합
        merged = " ".join(best_pair)
        replacement = "".join(best_pair)
        new_vocab = {}
        for word, freq in vocab.items():
            new_word = word.replace(merged, replacement)
            new_vocab[new_word] = freq
        vocab = new_vocab

    return vocab

corpus = ["low", "lower", "newest", "widest", "low", "low"]
simple_bpe(corpus, 5)

Word2Vec으로 보는 벡터 공간

# pip install gensim
from gensim.models import Word2Vec

# 간단한 학습 데이터
sentences = [
    ["왕", "은", "왕비", "와", "궁전", "에", "산다"],
    ["여왕", "은", "궁전", "을", "다스린다"],
    ["고양이", "는", "생선", "을", "좋아한다"],
    ["강아지", "는", "산책", "을", "좋아한다"],
]

model = Word2Vec(sentences, vector_size=50, window=3, min_count=1, epochs=100)

# 단어 벡터 확인
print(f"'왕' 벡터 차원: {model.wv['왕'].shape}")

# 유사 단어 찾기 (학습 데이터가 적어 정확도는 낮음)
similar = model.wv.most_similar("왕", topn=3)
for word, score in similar:
    print(f"  {word}: {score:.3f}")

토큰화는 LLM의 입구이고, 임베딩은 LLM이 언어를 이해하는 기반입니다. 내일은 이 임베딩 위에서 작동하는 Transformer 아키텍처를 배웁니다.

오늘의 연습문제

  1. tiktoken을 설치하고, 한국어 문장 3개와 영어 문장 3개를 각각 토큰화해보세요. 한국어가 몇 배 더 많은 토큰을 사용하는지 계산해보세요.
  2. BPE 알고리즘에서 병합(merge) 횟수를 늘리면 어휘 크기와 토큰 길이에 어떤 변화가 생기는지 실험해보세요.
  3. Word2Vec의 유명한 관계식 “왕 - 남자 + 여자 = 여왕”이 왜 성립하는지, 벡터 공간의 관점에서 설명해보세요.

이 글이 도움이 되었나요?